#include "jsonprase.h"
#include <QRegularExpression>
#include <QApplication>
#include <QFile>
#include <QTextStream>
#include "QDebug"
#include <QJsonArray>

JsonPrase::JsonPrase(QByteArray jsonData)
{
    Form stForm;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
    gJsonObj = jsonDoc.object();
    QList<QString> keys = gJsonObj.keys();
    foreach (const QString& key, keys) {
        stForm.QStrName = key;
        stForm.SubFormList.clear();
        stForm.FormObject = gJsonObj.value(key).toObject();
        JsonSubFormProc(&stForm);
        FormList.append(stForm);
    }
}

QList<Form>& JsonPrase::FormGet(void)
{
    return FormList;
}

QList<SubForm>& JsonPrase::SubFormGet(Form *pstForm)
{
    return pstForm->SubFormList;
}

QList<VariableObj>& JsonPrase::VarGet(SubForm *pstSubForm)
{
    return pstSubForm->VarList;
}

QList<OptionCfg>& JsonPrase:: ConfigGet(VariableObj *pstVariable)
{
    return pstVariable->CfgList;
}

void JsonPrase:: ConfigSet(OptionCfg *pstCfg, QVariant Value)
{
    switch (pstCfg->enType) {
        case CHECK:
        {
            pstCfg->CfgObject["CheckBox"] = (Value.toInt()) ? 1:0;
            break;
        }

        case NUM:
        case OPTION:
        {
            QJsonValue TmpValue = pstCfg->CfgObject.value("value_h");
            if ((!TmpValue.isNull()) && (!TmpValue.isUndefined()))
            {
                pstCfg->CfgObject["value_h"] = QJsonValue::fromVariant((double)(Value.toULongLong() >> 32));
            }

            pstCfg->CfgObject["value"] = QJsonValue::fromVariant((double)(Value.toULongLong() & 0x0FFFFFFFF));
            break;
        }

        case STRING:
        {
            pstCfg->CfgObject["value"] = Value.toString();
            break;
        }

        case LIST:
        {
            QJsonArray TmpArr = pstCfg->CfgObject.value("list").toArray();
            QList<QVariant> TmpList = Value.toList();
            for (quint32 i = 0; i < (quint32)TmpList.size(); i++)
            {
                TmpArr[i] =  QJsonValue::fromVariant(TmpList[i].toUInt());
            }

             pstCfg->CfgObject["list"] = TmpArr;
            break;
        }

    }
}

/*void JsonPrase::ConfigSet(quint64 ulFormIndex, quint64 ulSubFormIndex, OptionCfg stCfg)
{

}*/
void JsonPrase::SaveCfg(void)
{

    for (quint32 u32FormIndex = 0; u32FormIndex < (quint32)FormList.size(); u32FormIndex++)
    {
        QList<SubForm> TmpSubForms = FormList[u32FormIndex].SubFormList;
        for (quint32 u32SubFormIndex = 0; u32SubFormIndex < (quint32)TmpSubForms.size(); u32SubFormIndex++)
        {
            QList<VariableObj> TmpVars = TmpSubForms[u32SubFormIndex].VarList;
            for (quint32 u32VarIndex = 0; u32VarIndex < (quint32)TmpVars.size(); u32VarIndex++)
            {
                QList<OptionCfg> TmpCfgs = TmpVars[u32VarIndex].CfgList;
                for (quint32 u32CfgIndex = 0; u32CfgIndex < (quint32)TmpCfgs.size(); u32CfgIndex++)
                {
                    TmpVars[u32VarIndex].VarObject[TmpCfgs[u32CfgIndex].QStrName] = TmpCfgs[u32CfgIndex].CfgObject;
                }

                TmpSubForms[u32SubFormIndex].SubFormObject[TmpVars[u32VarIndex].QStrName] = TmpVars[u32VarIndex].VarObject;
            }

            FormList[u32FormIndex].FormObject[TmpSubForms[u32SubFormIndex].QStrName] = TmpSubForms[u32SubFormIndex].SubFormObject;
        }

        gJsonObj[FormList[u32FormIndex].QStrName] = FormList[u32FormIndex].FormObject;
    }

    QJsonDocument jsonDoc(gJsonObj);
    QString QStrDir = QString("%1").arg(QCoreApplication::applicationDirPath());
    QStrDir.append("/config/config");
    QString jsonString = jsonDoc.toJson(QJsonDocument::Indented);
    QFile Cfile(QStrDir);
    if (!Cfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
           qDebug("open fail");
           return ;
       }

       // 将JSON字符串写入文件
       QTextStream out(&Cfile);
       out << jsonString;
       Cfile.close();
       return;

}

void JsonPrase::JsonSubFormProc(Form *pstForm)
{
    SubForm stSubForm;

    QList<QString> keys = pstForm->FormObject.keys();
    foreach (const QString& key, keys) {
        stSubForm.QStrName = key;
        stSubForm.VarList.clear();
        stSubForm.SubFormObject = pstForm->FormObject.value(key).toObject();

        JsonVariableProc(&stSubForm);
        pstForm->SubFormList.append(stSubForm);
    }
}

void JsonPrase::JsonVariableProc(SubForm *pstSubForm)
{
    VariableObj stVarObj;

    QList<QString> keys = pstSubForm->SubFormObject.keys();
    foreach (const QString& key, keys) {
        stVarObj.QStrName = key;
        stVarObj.CfgList.clear();
        stVarObj.VarObject = pstSubForm->SubFormObject.value(key).toObject();

        JsonOptionProc(&stVarObj);
        pstSubForm->VarList.append(stVarObj);
    }
}


void JsonPrase::JsonOptionProc(VariableObj *pstVariable)
{
    OptionCfg stOptionCfg;
    /* subForm下有varible，varible下才是选项，所以需要过滤掉varible那层 */
    QList<QString> varkeys = pstVariable->VarObject.keys();
    foreach (const QString& subkey, varkeys) {
        stOptionCfg.QStrName = subkey;
        stOptionCfg.Option.clear();

        stOptionCfg.CfgObject = pstVariable->VarObject.value(subkey).toObject();

        stOptionCfg.QStrhelp = stOptionCfg.CfgObject.value("help").toString();

        QString tip = stOptionCfg.CfgObject.value("tips").toString();

        QRegularExpression minRegex("\\bMin(?:Size)?: (\\d+)\\b");
        QRegularExpressionMatch minMatch = minRegex.match(tip);

        QRegularExpression maxRegex("\\bMax(?:Size)?:(\\d+)\\b");
        QRegularExpressionMatch maxMatch = maxRegex.match(tip);
        stOptionCfg.u64Min = minMatch.captured(1).toULongLong();
        stOptionCfg.u64Max = maxMatch.captured(1).toULongLong();
           // stOptionCfg.u64Min = 0;
          //  stOptionCfg.u64Max = 10;
       // stOptionCfg.QStrhelp.append(tip);


        QJsonValue Value = stOptionCfg.CfgObject.value("value");

        QJsonValue Value_H = stOptionCfg.CfgObject.value("value_h");

        QJsonValue CheckBox = stOptionCfg.CfgObject.value("CheckBox");
        QJsonValue List = stOptionCfg.CfgObject.value("list");
        //QJsonValueRef testVal =CfgRef.toObject()["value"];

        if ((!CheckBox.isNull()) && (!CheckBox.isUndefined()))
        {

            stOptionCfg.QStrhelp.append(tip);
            stOptionCfg.enType = CHECK;
            stOptionCfg.value = CheckBox;
        }
        else if ((!List.isNull()) && (!List.isUndefined()))
        {
            stOptionCfg.enType = LIST;
            stOptionCfg.value = List;
            QRegularExpression regex("([^,;]+), Value:(\\d+)");
            QRegularExpressionMatchIterator iter = regex.globalMatch(tip);
            while (iter.hasNext()) {
                QRegularExpressionMatch match = iter.next();
                QString key = match.captured(1);
                int value = match.captured(2).toInt();
                stOptionCfg.Option.insert(key, value);
            }
        }
        else if ((!Value.isNull()) && (!Value.isUndefined()))
        {

            stOptionCfg.value = Value;
            stOptionCfg.u64val = (quint32)Value.toDouble();
            if ((!Value_H.isNull()) && (!Value_H.isUndefined()))
            {
               stOptionCfg.u64val += (((quint64)Value_H.toDouble()) << 32);
            }

            if (tip.contains("Value"))
            {
                stOptionCfg.enType = OPTION;

                QRegularExpression regex("([^,;]+), Value:(\\d+)");
                QRegularExpressionMatchIterator iter = regex.globalMatch(tip);
                while (iter.hasNext()) {
                    QRegularExpressionMatch match = iter.next();
                    QString key = match.captured(1);
                    int value = match.captured(2).toInt();
                    stOptionCfg.Option.insert(key, value);
                }

            }
            else if (tip.contains("MinSize"))
            {
                stOptionCfg.enType = STRING;
                stOptionCfg.QStrhelp = QString("MinSize: %1, MaxSize: %2;").arg(stOptionCfg.u64Min).arg(stOptionCfg.u64Max).append(stOptionCfg.QStrhelp);
            }
            else
            {
                stOptionCfg.QStrhelp = QString("Min: %1, Max: %2;").arg(stOptionCfg.u64Min).arg(stOptionCfg.u64Max).append(stOptionCfg.QStrhelp);
                stOptionCfg.enType = NUM;
            }
        }
        else
        {

            stOptionCfg.value = Value;
            stOptionCfg.enType = OPTION;
        }


        pstVariable->CfgList.append(stOptionCfg);

    }

}
